package com.grouponmall.service;

import java.util.ArrayList;
import java.util.List;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.nodes.TextNode;
import org.htmlparser.tags.Bullet;
import org.htmlparser.tags.CompositeTag;
import org.htmlparser.tags.Div;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.ParagraphTag;
import org.htmlparser.tags.Span;
import org.htmlparser.tags.TableColumn;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;

import com.grouponmall.model.Deal;

/**
 * @author xueqiang.mi
 * @since 2010-6-1
 */
public class RetrieveFromSocialBuy extends BaseRetrieveService {

  public static final String URL = "http://www.socialbuy.com/";
  public static final String SOURCE = "SocialBuy";

  @Override
  @SuppressWarnings("serial")
  public List<Deal> extract(String link) throws ParserException {
    List<Deal> deals = new ArrayList<Deal>();
    Deal deal = new Deal();
    deal.setSource(SOURCE);
    deal.setLink(link);

    int days = 0;
    int hours = 0;
    int minutes = 0;
    @SuppressWarnings("unused")
    int seconds = 0;
    Parser parser = new Parser(link);
    NodeList list = parser.extractAllNodesThatMatch(new NodeFilter() {
      public boolean accept(Node node) {
        if (node instanceof Div) {
          Div div = (Div) node;
          String clazz = div.getAttribute("class");
          if (clazz != null && (clazz.equals("main_img_mid") || clazz.equals("day") || clazz.equals("digital_clock"))) {
            return true;
          }
        } else if (node instanceof ParagraphTag) {
          CompositeTag p = (CompositeTag) node;
          String clazz = p.getAttribute("class");
          if (clazz != null && clazz.equals("city")) {
            return true;
          }
          if (p.getChildCount() == 3) {
            return true;
          }
        } else if (node instanceof TableColumn) {
          TableColumn td = (TableColumn) node;
          String clazz = td.getAttribute("class");
          if (clazz != null && clazz.equals("price")) {
            return true;
          }
          String valign = td.getAttribute("valign");
          if (valign != null && valign.equals("middle")) {
            return true;
          }
        }
        return false;
      }
    });

    for (Node node : list.toNodeArray()) {
      if (node instanceof ParagraphTag) {
        ParagraphTag para = (ParagraphTag) node;
        String clazz = para.getAttribute("class");
        if (clazz != null && clazz.equals("city")) {
          deal.setCity(para.getFirstChild().getText().trim());
        } else if (para.getFirstChild().getText().contains("Value")) {
          Span span = (Span) para.getChild(2);
          deal.setRetailValue(span.getFirstChild().getText());
        } else if (para.getFirstChild().getText().contains("Discount")) {
          Span span = (Span) para.getChild(2);
          deal.setDiscount(span.getFirstChild().getText());
        }
      } else if (node instanceof TableColumn) {
        TableColumn td = (TableColumn) node;
        String clazz = td.getAttribute("class");
        if (clazz != null && clazz.equals("price")) {
          String price = td.getFirstChild().getText();
          if (!price.startsWith("$")) {
            price = "$" + price;
          }
          deal.setPrice(price);
        }
        String valign = td.getAttribute("valign");
        if (valign != null && valign.equals("middle")) {
          deal.setTitle(td.getFirstChild().getText());
        }
      } else if (node instanceof Div) {
        Div div = (Div) node;
        String clazz = div.getAttribute("class");
        if (clazz.equals("main_img_mid")) {
          NodeList imageNodeList = node.getChildren().extractAllNodesThatMatch(new NodeFilter() {
            public boolean accept(Node node) {
              if (node instanceof ImageTag) {
                return true;
              }
              return false;
            }

          });
          for (Node n : imageNodeList.toNodeArray()) {
            // TODO: only extract one image
            ImageTag image = (ImageTag) n;
            deal.setImage(image.getAttribute("src"));
          }
        } else if (clazz.equals("day")) {
          if (div.getChildCount() > 2) {
            Node n = div.getChildren().toNodeArray()[1];
            if (n.getChildren().size() > 3) {
              n = n.getChildren().toNodeArray()[2];
              days = Integer.valueOf(n.getText().trim());
            }
          }
        } else if (clazz.equals("digital_clock")) {
          ParagraphTag p = (ParagraphTag) div.getChild(1);
          TextNode text = (TextNode) p.getChild(2);
          hours = Integer.valueOf(text.getText().trim());
          text = (TextNode) p.getChild(6);
          minutes = Integer.valueOf(text.getText().trim());
          text = (TextNode) p.getChild(10);
          seconds = Integer.valueOf(text.getText().trim());

          String timeLeft = new StringBuilder().append(days).append(" days ").append(hours).append(" hours ").append(
            minutes).append(" minutes").toString();
          deal.setTimeLeft(timeLeft);
        }
      }
    }

    deals.add(deal);
    return deals;
  }

  @Override
  @SuppressWarnings("serial")
  public NodeList getExpectedLinks(String link) throws ParserException {
    Parser parser = new Parser(link);
    NodeList list = parser.extractAllNodesThatMatch(new NodeFilter() {
      public boolean accept(Node node) {
        if (!(node instanceof Bullet) || node.getChildren().size() < 2) {
          return false;
        }
        return true;
      }
    });

    list = list.extractAllNodesThatMatch(new NodeFilter() {
      public boolean accept(Node node) {
        if (node instanceof LinkTag) {
          return true;
        }
        return false;
      }
    }, true);
    return list;
  }

  public String getURL() {
    return URL;
  }
}
